package com.hxgis.web.controller;

import com.es.common.domain.EsCondition;
import com.hxgis.common.base.ResultVO;
import com.hxgis.common.base.StationCache;
import com.hxgis.common.entity.RainstormInfo;
import com.hxgis.common.entity.Station;
import com.hxgis.common.entity.StationExtremeInfo;
import com.hxgis.common.enums.PreYear30Enum;
import com.hxgis.common.repository.*;
import com.hxgis.common.service.*;
import com.hxgis.common.utils.RectField;
import com.hxgis.common.utils.ResultVOUtil;
import com.hxgis.common.utils.TimeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 初始化暴雨过程和站点极端以及极值接口
 */
@RestController
@RequestMapping("init")
@Slf4j
@Api(tags = "InitController")
public class InitController {

    @Autowired
    StationInfoRepository stationInfoRepository;

    @Autowired
    RainDayInfoRepository rainDayInfoRepository;

    @Autowired
    RainstormInfoRepository rainstormInfoRepository;

    @Autowired
    RainstormFeatureInfoRepository featureInfoRepository;

    @Autowired
    StationDistance200Repository testGeoRepository;

    @Autowired
    StationService stationService;

    @Autowired
    RainDayService rainDayService;

    @Autowired
    RainstormInfoService rainstormInfoService;

    @Autowired
    RainstormFeatureService rainstormFeatureService;



    @Autowired
    RainstormCountService rainstomCountService;

    @Autowired
    RainstormCourseService rainstormCourseService;

    @Autowired
    private RainExtremeInfoService extremeInfoService;

    @Autowired
    private StationExtremeService stationExtremeService;

    @Autowired
    ProcRainInfoService procRainInfoService;

    @Autowired
    ExtremeProcService extremeProcService;


    @ApiOperation(value="初始化一段时间数据最好是一个月数据开始的时候跑一次就行了", notes="startTime：19511231，endTime：20190101")
    @GetMapping("initAllDataByDay")
    public ResultVO completionContinueByDay(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) {
        long s = System.currentTimeMillis();
        List<Station> stations = StationCache.getStations();
        List<String> stationIds = new ArrayList<>();
        stations.stream().forEach(x -> {
            stationIds.add(x.getStationNo());
        });
        List<String> stationNoList = RectField.getBeanFields(stations, "stationNo");

//        List<String> monthBetweenDateStr = null;
//        try {
//            monthBetweenDateStr = TimeUtil.getMonthBetweenDateStr(TimeUtil.preDay(startTime,1),
//                    TimeUtil.nextDay(endTime,1));
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
        //初始数据
//        monthBetweenDateStr.stream().forEach(x -> {
//            rainDayService.addToRainEs(x + "000000",stationIds);
//            log.info("当前正保存的年月是:{}",x);
//        });
        rainDayService.addToRainEs(TimeUtil.preDay(startTime,1), TimeUtil.nextDay(endTime,1), stationIds);
        log.info("{}到{}-----cimiss拉取元数据", TimeUtil.preDay(startTime,1), TimeUtil.nextDay(endTime,1));
        //保存暴雨数据
        rainstormInfoService.saveStorms(startTime, endTime, stationIds);
        //单日多日降水
        rainDayService.completionRainDay20(startTime, endTime, stationIds);
        rainDayService.completionRainDay08(startTime, endTime, stationIds);
        //连续降水和连续无降水过程
        rainDayService.completionContinueByYear20(startTime, endTime, stationIds);
        rainDayService.completionNotContinueByYear20(startTime, endTime, stationIds);
        rainDayService.completionContinueByYear08(startTime, endTime, stationIds);
        rainDayService.completionNotContinueByYear08(startTime, endTime, stationIds);
        //计算计算事件
        List<StationExtremeInfo> allExtreInfo = stationExtremeService.getAllExtreInfo();
        extremeInfoService.saveExtremeInfo(startTime, endTime, allExtreInfo);
        //算单站过程
        rainstormInfoService.transSingleStrom(startTime, endTime);
        log.info("计算单站过程用时:{}", System.currentTimeMillis() - s);
        //计算持续性暴雨过程
        rainstomCountService.countMain(startTime, endTime, stationNoList);
        log.info("计算持续性暴雨过程用时:{}", System.currentTimeMillis() - s);
        //计算暴雨组
        rainstormCourseService.countRainStormGroup(startTime, endTime, stationNoList);
        log.info("计算暴雨组用时:{}", System.currentTimeMillis() - s);
        //计算全国暴雨组过程
        rainstormCourseService.countRainStormAreaGroup(startTime, endTime);
        log.info("计算全国暴雨组过程用时:{}", System.currentTimeMillis() - s);
        //全国持续性暴雨特征分析单站过程
        rainstormFeatureService.transSingleStromByDay(startTime, endTime);
        log.info("全国持续性暴雨特征分析单站过程时:{}", System.currentTimeMillis() - s);
        //全国持续性暴雨特征分析区域过程
        rainstormFeatureService.featureAreaStrom(startTime, endTime, stationNoList);
        log.info("全国持续性暴雨特征分析区域过程:{}", System.currentTimeMillis() - s);
        log.info("终于算完啦:{}",System.currentTimeMillis() - s);
        return ResultVOUtil.success();
    }

    /**
     * 初始化数据接口
     * @param startYear
     * @param endYear
     * @return
     */
    @ApiOperation(value="初始化数据开始的时候跑一次就行了", notes="startYear：开始年，endYear：结束年")
    @GetMapping("/initAllData")
    public ResultVO initAllData(@RequestParam("startYear") Integer startYear,@RequestParam("endYear") Integer endYear) throws Exception{
        long ss = System.currentTimeMillis();
        List<Station> stations = stationService.selectAll();
        List<String> stationIds = new ArrayList<>();
        stations.stream().forEach(x -> {
            stationIds.add(x.getStationNo());
        });
        List<String> stationNoList = RectField.getBeanFields(stations, "stationNo");
        //todo 保存初始基础数据开始
        for (int i = startYear; i <= endYear; i++){
            log.info("当前正保存的年是:{}",i);
            long s = System.currentTimeMillis();
            //第一步将数据存入rainday  到时候打开
            for (int j = 1; j <= 12 ; j++){
                String firstDayOfMonth = TimeUtil.getFirstDayOfMonth(i, j);
                String lastDayOfMonth = TimeUtil.getLastDayOfMonth(i, j);
//                List<String> monthBetweenDateStr = TimeUtil.getMonthBetweenDateStr(TimeUtil.preDay(firstDayOfMonth,1),
//                        TimeUtil.nextDay(lastDayOfMonth,1));
//                monthBetweenDateStr.stream().forEach(x -> {
//                    rainDayService.addToRainEs(x + "000000",stationIds);
//                    log.info("当前正保存的年月是:{}",x);
//                });
                rainDayService.addToRainEs(TimeUtil.preDay(firstDayOfMonth,1), TimeUtil.nextDay(lastDayOfMonth,1), stationIds);
                log.info("{}到{}-----cimiss拉取元数据", TimeUtil.preDay(firstDayOfMonth,1), TimeUtil.nextDay(lastDayOfMonth,1));

            }
            log.info("从cimiss将日值数据导进来用时:{}",System.currentTimeMillis() - s);
            //筛选出暴雨存入暴雨信息  这里已经循环了年
            rainstormInfoService.initRainstormInfoToEs(String.valueOf(i),String.valueOf(i));
            log.info("筛选暴雨数据进暴雨表用时:{}",System.currentTimeMillis() - s);
            log.info("总共用时:{}",System.currentTimeMillis() - s);
        }
        //todo 保存初始基础数据结束

        //todo 计算极值排位数据开始
        for (int i = Integer.valueOf(startYear); i <= Integer.valueOf(endYear); i++) {
            //第一步将数据存入rainday
            for (int j = 1; j <= 12; j++) {
                String firstDayOfMonth = TimeUtil.getFirstDayOfMonth(i, j);
                String lastDayOfMonth = TimeUtil.getLastDayOfMonth(i, j);
                //单日多日降水
                rainDayService.completionRainDay20(firstDayOfMonth, lastDayOfMonth, stationIds);
                rainDayService.completionRainDay08(firstDayOfMonth, lastDayOfMonth, stationIds);
                //todo 防止es还没完全存进去 会有短暂延时
                try {
                    TimeUnit.SECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //todo 连续降水和连续无降水过程  旧版本
//                rainDayService.completionContinueByYear20(firstDayOfMonth, lastDayOfMonth, stations);
//                rainDayService.completionNotContinueByYear20(firstDayOfMonth, lastDayOfMonth, stations);
//                rainDayService.completionContinueByYear08(firstDayOfMonth, lastDayOfMonth, stations);
//                rainDayService.completionNotContinueByYear08(firstDayOfMonth, lastDayOfMonth, stations);
            }
        }
        //todo 连续降水和连续无降水过程  新版本
        rainDayService.completionContinueByYear20New(startYear + "0101",endYear + "1231");
        rainDayService.completionNotContinueByYear20New(startYear + "0101",endYear + "1231");
        rainDayService.completionContinueByYear08New(startYear + "0101",endYear + "1231");
        rainDayService.completionNotContinueByYear08New(startYear + "0101",endYear + "1231");

        //todo 计算极值排位数据结束

        //todo 这里可能需要先计算阈值  阈值需要把所有的降水数据和连续降水连续无降水跑完才行
        stationExtremeService.saveExtremeInfo(PreYear30Enum.PRE_YEAR_30_START.getYear() + "0101",
                PreYear30Enum.PRE_YEAR_30_END.getYear() + "1231", stationIds);

        //todo 跑极端事件数据
        List<StationExtremeInfo> allExtreInfo = stationExtremeService.getAllExtreInfo();
        for (int i = startYear; i <= endYear; i++) {
            for (int j = 1; j <= 12; j++) {
                String firstDayOfMonth = TimeUtil.getFirstDayOfMonth(i, j);
                String lastDayOfMonth = TimeUtil.getLastDayOfMonth(i, j);
                extremeInfoService.saveExtremeInfo(firstDayOfMonth, lastDayOfMonth, allExtreInfo);
            }
        }

        for (int i = startYear; i <= endYear; i++) {
            //筛选出降水表原数据的过程数据出来
            procRainInfoService.saveProRainInfoByTime(i+"0101", i+"1231" );
        }

        log.info("初始化过程数据");
        for (int i = startYear; i <= endYear; i++) {
            extremeProcService.saveExtremeProcByTime(i+"0101", i+"1231", allExtreInfo);
        }
        log.info("初始化极端过程数据完成");

        //todo 为了保证基础信息完成后再计算各种方法
        countStormInfo(startYear, endYear, stationNoList);
        log.info("终于算完啦:{}",System.currentTimeMillis() - ss);
        return ResultVOUtil.success("终于算完啦:{}");
    }

    @ApiOperation(value="初始化暴雨相关数据", notes="startYear：开始年，endYear：结束年")
    @GetMapping("/initStormData")
    public ResultVO initStormData(@RequestParam("startYear") Integer startYear,@RequestParam("endYear") Integer endYear) throws Exception{
        long ss = System.currentTimeMillis();
        List<Station> stations = stationService.selectAll();
        List<String> stationIds = new ArrayList<>();
        stations.stream().forEach(x -> {
            stationIds.add(x.getStationNo());
        });
        List<String> stationNoList = RectField.getBeanFields(stations, "stationNo");
        countStormInfo(startYear, endYear, stationNoList);
        log.info("终于算完啦:{}",System.currentTimeMillis() - ss);
        return ResultVOUtil.success("终于算完啦:{}");
    }

    //将降雨数据保存到极端数据表

    /**
     * 计算各种算法
     * @param startYear
     * @param endYear
     * @param stationNoList
     */
    private void countStormInfo(Integer startYear, Integer endYear, List<String> stationNoList) {
        for (int i = startYear; i <= endYear; i++) {
            log.info("当前正保存的年是:{}", i);
            long s = System.currentTimeMillis();
            //算单站过程
            rainstormInfoService.transSingleStrom(i + "0101", i + "1231");
            log.info("计算单站过程用时:{}", System.currentTimeMillis() - s);
            //todo 防止es还没完全存进去 会有短暂延时
            try {
                TimeUnit.SECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //计算暴雨组单站过程
            rainstormCourseService.countRainStormGroup(i + "0101", i + "1231", stationNoList);
            log.info("计算暴雨组用时:{}", System.currentTimeMillis() - s);
            //todo 防止es还没完全存进去 会有短暂延时
            try {
                TimeUnit.SECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //计算持续性暴雨区域过程
            rainstomCountService.countMain(i + "0101", i + "1231", stationNoList);
            log.info("计算持续性暴雨过程用时:{}", System.currentTimeMillis() - s);

            //计算全国暴雨组区域过程
            rainstormCourseService.countRainStormAreaGroup(i + "0101", i + "1231");
            log.info("计算全国暴雨组过程用时:{}", System.currentTimeMillis() - s);
            //全国持续性暴雨特征分析单站过程
            rainstormFeatureService.transSingleStrom(i+"", i+"" );
            log.info("全国持续性暴雨特征分析单站过程时:{}", System.currentTimeMillis() - s);
            //todo 防止es还没完全存进去 会有短暂延时
            try {
                TimeUnit.SECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //全国持续性暴雨特征分析区域过程
            rainstormFeatureService.featureAreaStrom(i + "0101", i + "1231", stationNoList);
            log.info("全国持续性暴雨特征分析区域过程:{}", System.currentTimeMillis() - s);
            log.info("总共用时:{}", System.currentTimeMillis() - s);

        }
    }


    @RequestMapping("/count/rainstom")
    public String rainstomCount(@RequestParam("startTime") String startTime,
                                @RequestParam("endTime") String endTime){
        EsCondition esCondition = new EsCondition();
        esCondition.size(10000);
        List<Station> stations = stationInfoRepository.selectList(esCondition);
        List<String> stationNoList = RectField.getBeanFields(stations, "stationNo");
        rainstomCountService.countMain(startTime,endTime,stationNoList);
        return "初始化成功";
    }


//    @GetMapping("/clear/courseArea")
    public String clearCourseArea(@RequestParam("startTime") String startTime,
                                   @RequestParam("endTime") String endTime){
        EsCondition rainStormCondition = EsCondition.getEsCondition();
//        rainStormCondition.
        rainStormCondition.eq("courseNum",null).not()
                .GTE("time", Long.valueOf(startTime))
                .LTE("time", Long.valueOf(endTime));
        rainStormCondition.size(100000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
        rainstormInfos.stream().forEach(x -> {
            x.setCourseNum(null);
            x.setCourseArea(null);
        });
        rainstormInfoRepository.saveBatch(rainstormInfos);
        return "sucess";
    }


//    @GetMapping("/clear/nationGroup")
    public String clearNationGroup(){
        EsCondition rainStormCondition = EsCondition.getEsCondition();
        rainStormCondition.eq("nationAreaGroup",null).not();
        rainStormCondition.size(10000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
        rainstormInfos.stream().forEach(x -> {
            x.setNationAreaGroup(null);
            x.setCourseContinue(null);
        });
        rainstormInfoRepository.saveBatch(rainstormInfos);
        return "sucess";
    }







}
